/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine.command;

import java.util.Vector;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.StateMachine;

import com.cea.papyrus.core.commands.GraphNodeSetConstraintCommand;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.statemachine.helper.NodeRegionHelper.Zone;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Property;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * A command to specifically resize graph nodes attached to a state machine
 * and its embedded regions.
 * 
 * @author David Servat
 * @since 29 jan. 07
 */

public class ResizeStateMachineNodeCommand extends Command {

	/**
	 * Debug channel.
	 */
	private int channel = 501;

	/**
	 * The stateMachine to resize.
	 */
	private GraphNode statemachine = null;

	/**
	 * The request to perform.
	 */
	private ChangeBoundsRequest request = null;

	/**
	 * The constraint rectangle.
	 */
	private Rectangle constraint = null;

	/**
	 * The compound command to perform resize.
	 */
	private CompoundCommand compoundCommand = null;

	/**
	 * The constructor.
	 * 
	 * @param constraintToApply 
	 * @param constraint the constraint to be applied
	 * @param stateMachineToResize the graph node associated to the state machine
	 * @param requestTobePerformed the request which triggered this resize
	 * @param requestToPerform 
	 */
	public ResizeStateMachineNodeCommand(GraphNode stateMachineToResize, ChangeBoundsRequest requestToPerform, Rectangle constraintToApply){
		Debug.debug(this, "call ResizeStateMachineNodeCommand(GraphNode stateMachineToResize, ChangeBoundsRequest requestToPerform, Rectangle constraintToApply)", channel);

		//a bunch of precautionary tests
		if((stateMachineToResize == null) || (requestToPerform == null) || (constraintToApply == null))
			throw new IllegalArgumentException();

		if(stateMachineToResize.getSemanticModel() == null) 
			throw new IllegalArgumentException();

		Element elt = ((Uml1SemanticModelBridge)stateMachineToResize.getSemanticModel()).getElement();
		if(elt == null)
			throw new IllegalArgumentException();

		if(!(elt instanceof StateMachine))
			throw new IllegalArgumentException();

		//now we are sure to have received a correct graph node linked to a state machine
		//we store the infos
		statemachine = stateMachineToResize;
		request = requestToPerform;
		constraint = constraintToApply;
	}

	/**
	 * Calls the redo() method, hence the internaly computed compoundCommand is recomputed.
	 * This deals with the case when undo/redo have been performed on a region creation
	 * and the resize command may no longer be valid.
	 */
	@Override
	public void execute(){
		Debug.debug(this, "call ResizeStateMachineNodeCommand.execute()", channel);

		redo();
	}

	/**
	 * This rather long method actually computes the compound command to perform resize.
	 * It consists in testing the direction of resize and perform various translation/scaling
	 * on the embedded nodes w.r.t. to their positions to the borders of the state machine node.
	 * The code is long because the symmetry of processing is not easy to figure out.
	 * Explicit duplicated codes is better for comprehension.
	 * At the end the compund command is executed.
	 * Note: initializations have to take place just before execution of the command as there might have been
	 * some changes in the underlying structure - e.g. when undo/redo region creation have been made.
	 */
	@Override
	public void redo(){
		Debug.debug(this, "call ResizeStateMachineNodeCommand.redo()", channel);

		//a bunch of initializations
		int direction = request.getResizeDirection();
		int dx = request.getSizeDelta().width;
		int dy = request.getSizeDelta().height;

		//we erase the contents if any of the previous compound command
		compoundCommand = new CompoundCommand();

		//a single unit command to be used throughout the code
		GraphNodeSetConstraintCommand command;
		//a rectangle to embed the new dimensions
		Rectangle rect;
		//a temporary list of nodes
		Vector<DiagramElement> todoList;

		//first resize the state machine node with the constraint provided
		command = new GraphNodeSetConstraintCommand(statemachine, request, constraint);
		compoundCommand.add(command);

		//then we need to check the contents of the state machine node

		//we start by the first contained node of the statemachine node
		GraphNode startNode = (GraphNode)statemachine.getContained().get(0);

		//test the direction of resize
		//the processing depends on the direction
		//basically embedded nodes to be either scaled and/or translated along one or two axis
		//depending on their relative positions to the borders of the state machine
		switch(direction){
		case PositionConstants.WEST:
			Debug.debug(this, "State machine WEST expansion", channel);

			//this first node needs to be scaled along X
			//we add dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, 0));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current =(GraphNode) todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer LEFT border
					//this is the case if it has no LEFT neighbours at all
					if(!Zone.hasLeftNeighbours(currentLocation)){
						//these nodes need to be scaled
						//we add dx to its width
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					else{
						//in other cases the node needs to be translated
						//for each of these we translate their x of dx
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(dx, 0), current.getSize().getCopy());
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todo list
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.EAST:
			Debug.debug(this, "State machine EAST expansion", channel);

			//this first node needs to be scaled along X
			//we add dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, 0));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer RIGHT border
					//this is the case if it has no RIGHT neighbours at all
					if(!Zone.hasRightNeighbours(currentLocation)){
						//these nodes need to be scaled
						//for each of these we add dx to their width
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
						//then two possibilities
						//either the current node is a region
						//or it is a splitter
						//and we need to add its children to the todoList
						if(current.getSemanticModel() == null)
							todoList.addAll(current.getContained());
					}
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.NORTH:
			Debug.debug(this, "State machine NORTH expansion", channel);

			//this first node needs to be scaled along Y
			//we add dy to its height
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(0, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer TOP border
					//this is the case if it has no TOP neighbours at all
					if(!Zone.hasTopNeighbours(currentLocation)){
						//these nodes need to be scaled
						//for each of these we add dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					else{
						//in other cases the node needs to be translated
						//for each of these we translate their y of dy
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(0, dy), current.getSize().getCopy());
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todoList
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.SOUTH:
			Debug.debug(this, "State machine SOUTH expansion", channel);

			//this first node needs to be scaled along Y
			//we add dy to its height
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(0, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current =(GraphNode) todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer BOTTOM border
					//this is the case if it has no BOTTOM neighbours at all
					if(!Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale
						//for each of these we add dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
						//then two possibilities
						//either the current node is a region
						//or it is a splitter
						//and we need to add its children to the todoList
						if(current.getSemanticModel() == null)
							todoList.addAll(current.getContained());
					}
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.NORTH_WEST:
			Debug.debug(this, "State machine NORTH_WEST expansion", channel);

			//this first node needs to be scaled in both directions
			//we add dy to its height and dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer TOP and LEFT borders
					//this is the case if it has no LEFT neighbours nor TOP neigbours at all
					if(!Zone.hasLeftNeighbours(currentLocation) && !Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale both ways
						//for each of these we add dx to their width and dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//the second case is when it has no LEFT neighbours but TOP ones, i.e. close to LEFT border only
					else if(!Zone.hasLeftNeighbours(currentLocation) && Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale X and translate Y
						//for each of these we add dx to their wodth and translate their y of dy
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(0, dy), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//in the reverse case, i.e. close to TOP border only
					else if(Zone.hasLeftNeighbours(currentLocation) && !Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the scale Y and translate X
						//for each of these we add dy to their height and translate their x of dx
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(dx, 0), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					else{
						//in other cases the node needs to be translated both ways
						//for each of these we translate their x of dx and their y of dy
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(dx, dy), current.getSize().getCopy());
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todoList
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.NORTH_EAST:
			Debug.debug(this, "State machine NORTH_EAST expansion", channel);

			//this first node needs to be scaled in both directions
			//we add dy to its height and dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer TOP and RIGHT borders
					//this is the case if it has no RIGHT neighbours nor TOP neigbours at all
					if(!Zone.hasRightNeighbours(currentLocation) && !Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale both ways
						//for each of these we add dx to their width and dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//the second case is when it has no RIGHT neighbours but TOP ones, i.e. close to RIGHT border only
					else if(!Zone.hasRightNeighbours(currentLocation) && Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale X and translate Y
						//for each of these we add dx to their width and translate their y of dy
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(0, dy), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//in the reverse case, i.e. close to TOP border only
					else if(Zone.hasRightNeighbours(currentLocation) && !Zone.hasTopNeighbours(currentLocation)){
						//we need to add it to the scale Y
						//for each of these we add dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					else{
						//in other cases the node needs to be translated along Y
						//for each of these we translate their y of dy
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(0, dy), current.getSize().getCopy());
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todoList
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.SOUTH_WEST:
			Debug.debug(this, "State machine SOUTH_WEST expansion", channel);

			//this first node needs to be scaled in both directions
			//we add dy to its height and dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer BOTTOM and LEFT borders
					//this is the case if it has no LEFT neighbours nor BOTTOM neigbours at all
					if(!Zone.hasLeftNeighbours(currentLocation) && !Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale both ways
						//for each of these we add dx to their width and dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//the second case is when it has no LEFT neighbours but BOTTOM ones, i.e. close to LEFT border only
					else if(!Zone.hasLeftNeighbours(currentLocation) && Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale X
						//for each of these we add dx to their width
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//in the reverse case, i.e. close to BOTTOM border only
					else if(Zone.hasLeftNeighbours(currentLocation) && !Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the scale Y and translate X
						//for each of these we add dy to their height and translate their x of dx
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(dx, 0), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					else{
						//in other cases the node needs to be translated in X
						//for each of these we translate their x of dx
						rect = new Rectangle(current.getPosition().getCopy().getTranslated(dx, 0), current.getSize().getCopy());
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todoList
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		case PositionConstants.SOUTH_EAST:
			Debug.debug(this, "State machine SOUTH_EAST expansion", channel);

			//this first node needs to be scaled in both directions
			//we add dy to its height and dx to its width
			rect = new Rectangle(startNode.getPosition().getCopy(), startNode.getSize().getCopy().expand(dx, dy));
			//and create a unit command to do that
			command = new GraphNodeSetConstraintCommand(startNode, request, rect);
			//then add the unit command to the compound command
			compoundCommand.add(command);

			//then two possibilities
			//either this startNode is a region
			//in this case there is nothing more to do
			//or it is a splitter and we need to search further down with the children nodes
			//hence this big if-block

			todoList = new Vector<DiagramElement>();
			if(startNode.getSemanticModel() == null){
				todoList.addAll(startNode.getContained());
				//the todoList will be updated throughout the search
				while(!todoList.isEmpty()){
					GraphNode current = (GraphNode)todoList.firstElement();
					String currentLocation = ((Property)current.getProperty("zone")).getValue();
					//we test whether the current node is close to the outer BOTTOM and RIGHT borders
					//this is the case if it has no RIGHT neighbours nor BOTTOM neigbours at all
					if(!Zone.hasRightNeighbours(currentLocation) && !Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale both ways
						//for each of these we add dx to their width and dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//the second case is when it has no RIGHT neighbours but BOTTOM ones, i.e. close to RIGHT border only
					else if(!Zone.hasRightNeighbours(currentLocation) && Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the list of nodes to scale X
						//for each of these we add dx to their width
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(dx, 0));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}
					//in the reverse case, i.e. close to BOTTOM border only
					else if(Zone.hasRightNeighbours(currentLocation) && !Zone.hasBottomNeighbours(currentLocation)){
						//we need to add it to the scale Y
						//for each of these we add dy to their height
						rect = new Rectangle(current.getPosition().getCopy(), current.getSize().getCopy().expand(0, dy));
						//and create a unit command to do that
						command = new GraphNodeSetConstraintCommand(current, request, rect);
						//then add the unit command to the compound command
						compoundCommand.add(command);
					}

					//then two possibilities
					//either the current node is a region
					//or it is a splitter
					//and we need to add its children to the todoList
					if(current.getSemanticModel() == null)
						todoList.addAll(current.getContained());
					//we dealt with this node, thus remove it from the todoList
					todoList.remove(0);
				}//while
			}//if startNode is a splitter
			break;
		}
		compoundCommand.execute();
	}

	/**
	 * This method amounts to perform an undo() on the internaly computed compoundCommand.
	 */
	@Override
	public void undo(){
		Debug.debug(this, "call ResizeStateMachineNodeCommand.undo()", channel);

		compoundCommand.undo();
	}

}
